﻿using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Threading;
using tjb.Utility;
using tjb.Utility.Setting;
using tjb.Utility.Reflection;
using tjb.Utility.Gather;
using System.Collections;
using System.IO;
using tjb.Utility.IniReadWrite;
using System.ComponentModel;
using System.Runtime.Serialization.Formatters.Binary;
using System.Text;
using System.Reflection;
using System.Security.Permissions;
using System.Security.Policy;
using System.Security.Cryptography;

namespace tjb.ConsoleTest
{


    class Program
    {
        static void DisplayStrongName(Assembly assembly)
        {

            AssemblyName name = assembly.GetName();

            byte[] publicKey = name.GetPublicKey();

            StrongNamePublicKeyBlob blob = new StrongNamePublicKeyBlob(publicKey);

            StrongName sn = new StrongName(blob, name.Name, name.Version);

            Console.WriteLine(sn.Name);

            Console.WriteLine(sn.Version);

            Console.WriteLine(sn.PublicKey);



        }

        static void dMain()
        {

            Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();

            foreach (Assembly assembly in assemblies)
            {
                DisplayStrongName(assembly);
            }

            Console.ReadLine();

        }



        static void _Main(string[] args)
        {

            //   RSACrypto.StartDemo();
            // Console.ReadLine();
        }


    }

    class Grass
    {
        public static void Main()
        {
            string source = "内容";
            //  byte[] bytesutf8 = Encoding.GetEncoding("gb2312").GetBytes(source);
            byte[] bytesutf8 = Encoding.Unicode.GetBytes(source);
            var sb = new StringBuilder();
            for (int i = 0, n = bytesutf8.Length; i < n; i += 2)
            {
                sb.AppendFormat("&#x{0};", bytesutf8[i + 1].ToString("x2") + bytesutf8[i].ToString("x2"));

            }
            Console.WriteLine(sb);
            Console.WriteLine(BitConverter.ToString(bytesutf8));
            Console.ReadLine();
        }


        static byte[] signature;
        static byte[] hashOfExe;

        public static void Main1()
        {
            byte[] exe;
            using (FileStream fs = new FileStream("tjb.ConsoleTest.exe", FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
            {
                int len = (int)fs.Length;
                exe = new byte[len];
                fs.Read(exe, 0, len);
            }

            signature = Assembly.GetEntryAssembly().GetName().GetPublicKeyToken();
            hashOfExe = SHA1.Create().ComputeHash(exe);

            Console.WriteLine("About to VERIFY SIGNATURE with doChangeAlgId = FALSE");
            Teste_RSAFromAssembly_Verify(false);
            Console.WriteLine("Done");
            Console.WriteLine();

            try
            {
                Console.WriteLine("About to ENCRYPT with doChangeAlgId = FALSE");
                Teste_RSAFromAssembly(false);
                Console.Write("Done");
                Console.WriteLine();
            }
            catch
            {
                Console.WriteLine("Oops! - EXCEPTION");
                Console.WriteLine();
            }

            Console.WriteLine("About to VERIFY SIGNATURE with doChangeAlgId = TRUE");
            Teste_RSAFromAssembly_Verify(true);
            Console.WriteLine("Done");
            Console.WriteLine();

            Console.WriteLine("About to ENCRYPT with doChangeAlgId = TRUE");
            Teste_RSAFromAssembly(true);
            Console.WriteLine("Done");
            Console.WriteLine();

            ConsoleKeyInfo s = new ConsoleKeyInfo('s', ConsoleKey.A, false, false, false);

            Console.WriteLine(s == Console.ReadKey());
            Console.ReadKey();
        }

        public static void Teste_RSAFromAssembly(bool doChangeAlgId)
        {
            string clearText = "Teste de criptografia";
            byte[] byteText = System.Text.Encoding.Unicode.GetBytes(clearText);

            //Get assembly publickey --> 160 - 12(header) = 148 bytes 
            byte[] cspBlobAssembly = GetCspBlobAssembly(Assembly.GetExecutingAssembly(), doChangeAlgId);

            //Create the RSA based on the assembly publickey 
            RSACryptoServiceProvider rsaAssembly = new RSACryptoServiceProvider();
            rsaAssembly.ImportCspBlob(cspBlobAssembly);

            //Try to encrypt - error: "Key not valid for use in specified state." 
            byte[] textoCriptografado = rsaAssembly.Encrypt(byteText, false);

            //Executing one of the two lines below, the encrypt will start to work 
            rsaAssembly.ImportParameters(rsaAssembly.ExportParameters(false));
            rsaAssembly.FromXmlString(rsaAssembly.ToXmlString(false));

            //Get CspBlob from RSA 
            byte[] cspBlobRSA = rsaAssembly.ExportCspBlob(false);

            //Compare he sixth byte - only this byte is different 
            bool flagEqual = cspBlobRSA[5] == cspBlobAssembly[5]; //flagEqual == false!!! 

            //Try to encrypt - error does not occours any more 
            textoCriptografado = rsaAssembly.Encrypt(byteText, false);
        }

        public static bool Teste_RSAFromAssembly_Verify(bool doChangeAlgId)
        {
            string clearText = "Teste de criptografia";
            byte[] byteText = System.Text.Encoding.Unicode.GetBytes(clearText);

            //Get assembly publickey --> 160 - 12(header) = 148 bytes 
            byte[] cspBlobAssembly = GetCspBlobAssembly(Assembly.GetExecutingAssembly(), doChangeAlgId);

            //Create the RSA based on the assembly publickey 
            RSACryptoServiceProvider rsaAssembly = new RSACryptoServiceProvider();
            rsaAssembly.ImportCspBlob(cspBlobAssembly);

            return rsaAssembly.VerifyHash(hashOfExe, CryptoConfig.MapNameToOID("SHA1"), signature);
        }

        private static byte[] GetCspBlobAssembly(Assembly assembly, bool doChangeAlgId)
        {
            byte[] publicKeyAssembly = assembly.GetName().GetPublicKey();
            int size = publicKeyAssembly.Length - 12;
            byte[] retorno = new byte[size];
            Buffer.BlockCopy(publicKeyAssembly, 12, retorno, 0, size);
            if (doChangeAlgId)
                retorno[5] = (byte)(0x80 | retorno[5]);
            return retorno;
        }
    }

    // Output: 
    // About to VERIFY SIGNATURE with doChangeAlgId = FALSE 
    // Done 

    // About to ENCRYPT with doChangeAlgId = FALSE 
    // Oops! - EXCEPTION 

    // About to VERIFY SIGNATURE with doChangeAlgId = TRUE 
    // Done 

    // About to ENCRYPT with doChangeAlgId = TRUE 
    // Done 



}